package org.nf.db.util.converter;

import org.nf.db.util.TypeConverter;

import java.sql.Time;
import java.sql.Timestamp;
import java.time.*;
import java.util.Date;

/**
 * @author wangl
 * @date 2023/4/7
 */
public class DateConverter implements TypeConverter {

    @Override
    public boolean supports(Class<?> fieldType) {
        String targetType = fieldType.getName();
        return switch (targetType) {
            case "java.util.Date", "java.sql.Timestamp", "java.sql.Date", "java.sql.Time" -> true;
            default -> false;
        };
    }

    @Override
    public Object apply(Class<?> fieldType,Object value) {
        String targetType = fieldType.getName();
        long time = getTime(value);
        return switch (targetType) {
            case "java.util.Date" -> new Date(time);
            case "java.sql.Date" -> new java.sql.Date(time);
            case "java.sql.Time" -> new Time(time);
            case "java.sql.Timestamp" -> new Timestamp(time);
            default -> null;
        };
    }

    private long getTime(Object value) {
        return switch (value) {
            case Date date -> date.getTime();
            case LocalDateTime localDateTime -> localDateTimeToDate(localDateTime).getTime();
            case LocalDate localDate -> localDateToDate(localDate).getTime();
            case LocalTime localTime -> localTimeToDate(localTime).getTime();
            default -> throw new RuntimeException("Unable to convert " + value.getClass() + ".");
        };
    }

    private Date localDateTimeToDate(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zoneId).toInstant();
        return Date.from(instant);
    }

    private Date localDateToDate(LocalDate localDate) {
        ZoneId zoneId = ZoneId.systemDefault();
        Instant instant = localDate.atStartOfDay().atZone(zoneId).toInstant();
        return Date.from(instant);
    }

    private Date localTimeToDate(LocalTime localTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        Instant instant = localTime.atDate(LocalDate.now()).atZone(zoneId).toInstant();
        return Date.from(instant);
    }
}
